Lab 04 - Architektury behawioralne

Lab. 04 - Architektury behawioralne

Przykład robota sterowanego drzewem behawioralnym

1. Czym są architektury behawioralne?

Architektury behawioralne to takie podejście do sterowania robotami, gdzie robot wykonuje z góry zaprogramowane zachowania. Ich wygląd i priorytety są ustalane przez programistów.

Na zajęciach skupimy się na drzewach behawioralnych, którego przykład jest widoczny poniżej:
Behavior tree modelling the search and grasp plan of a two-armed robot.
Drzewo behawioralne modelujące poszukiwanie i chwytanie przedmiotu przez dwuramiennego robota. źródło

Będziemy korzystać z biblioteki py_trees (link) i jej rozszerzenia py_trees_ros (link).

Zachowania (Behaviours)

Są to najmniejsze elementy drzewa. Reprezentują najczęściej sprawdzanie warunków albo wykonywanie działań. Np. “Czy obiekt jest chwycony?” albo “Chwyć obiekt jedną ręką”.

Każde zachowanie ma metodę, która jest wywoływana tuż po jego pierwszym uruchomieniu (initialise), metodę, która jest wywoływana przy każdym uruchomieniu zachowania (update), oraz metodę, która jest wywoływana po jego zakończeniu, powodzeniem lub nie (terminate). Istnieje również metoda setup wywoływana podczas przygotowywania drzewa.

Poza tym, każde zachowanie ma jeszcze swój status (SUCCESS, FAILURE, RUNNING oraz INVALID), a także feedback message, czyli wiadomość pomagającą śledzić co zachowanie aktualnie robi.

Kompozycje (Composites)

Kierują one sposobem przechodzenia po zachowaniach. W py_trees mamy dostępne następujące kompozycje:

Dekoratory (Decorators)

Inaczej kapelusze (ang. hats), zarządzają działaniem pojedynczych dzieci, modyfikując je w jakiś sposób. Pełna lista jest długa, ale jedne z istotniejszych to:

Tablice (Blackboards)

Jest to przestrzeń wymiany danych między zachowaniami. Ta koncepcja najbardziej kłóci się z koncepcjami ROSa (tam node’y komunikują się przez topici), ale z założenia drzewa behawioralne działają synchronicznie, a ROS asynchronicznie. Dlatego, w przypadku takiego sterowania, nie możemy wywoływać żadnych callbacków. W py_trees_ros zostały utworzone klasy pozwalająca tworzyć subskrybenta topica, która synchronicznie, za każdym jej wywołaniem, udostępnia te dane na tablicy. Mają one różne sposoby działania, więcej w dokumentacji.

Po co to wszystko?

Uniwersalność

Drzewa behawioralne są szczególnie popularne podczas rozwijania gier. Możliwość stworzenia uniwersalnych zachowań, które dla różnych obiektów można łączyć w różne drzewa (często graficznie) pozwala na dużą uniwersalność stworzonego kodu. Wszelkie systemy z wieloma robotami też z tej zalety mogą korzystać.

Czytelność

Drzewa behawioralne są bardzo łatwe do interpretacji. Biblioteki mają natywnie wbudowane metody podglądu nie tylko architektury drzewa, ale również stanów i feedbacków podczas działania. Przez to również analiza i debugowanie staje się prostsze.

2. Cel zajęć

Celem tych zajęć będzie przygotowanie robota, który będzie realizował drzewo behawioralne zgodnie z założeniami:

Pożądane działanie zostało przedstawione na GIFie na górze instrukcji.

3. Przygotowanie środowiska

Przed przystąpieniem do pracy należy przygotować środowisko: Instrukcja przygotowania środowiska do zajęć.

Domyślnie kontener nosi nazwę ARM_04.

UWAGA! Skrypty po uruchomieniu usuwają kontener o takiej nazwie przed utworzeniem nowego.

Korzystanie z kontenera

Po każdym ponownym uruchomieniu komputera, proszę pamiętać o wywoływaniu:

xhost +local:root

Nowy terminal można dołączyć do kontenera korzystając z polecenia:

docker exec -it ARM_04 bash

ROS_DOMAIN_ID

W przypadku pracy na wielu komputerach w tej samej sieci lokalnej (eduroam też może tego wymagać), konieczne może być ustawienie zmiennej środowiskowej ROS_DOMAIN_ID na różnych wartościach. Należy wybrać dowolną liczbę całkowitą z zakresu 0-100. Wartość tę należy ustawić w pliku ~/.bashrc:

export ROS_DOMAIN_ID=10  # przykładowa wartość

lub bezpośrednio w terminalu (wtedy będzie obowiązywać tylko w tym terminalu):

export ROS_DOMAIN_ID=10  # przykładowa wartość

Sugerowane jest użycie dwóch ostatnich cyfr numeru IP komputera jako wartości ROS_DOMAIN_ID, aby uniknąć konfliktów z innymi użytkownikami w sieci. Aby sprawdzić swój adres IP, można użyć polecenia:

ip addr show

adres IP będzie widoczny przy interfejsie sieciowym, np. wlan0 lub eth0.

Wygodne może być dodanie tego exportu do bashrc:

echo 'export ROS_DOMAIN_ID=<wybrana_wartość>' >> ~/.bashrc 

4. Uruchomienie symulacji

W tej instrukcji będziemy ponownie wykorzystywać robota TurtleBot3, tym razem w świecie world1.sdf z paczki turtlebot3_bt. Można ją uruchomić poleceniem

cd /arm_ws
ros2 launch turtlebot3_bt turtlebot3_world1.launch.py

W przypadku błędów związanych z uruchomieniem symulacji proszę wywołać te polecenia:

source /usr/share/gazebo/setup.bash
source /usr/share/gazebo-11/setup.bash
ros2 launch turtlebot3_bt turtlebot3_world1.launch.py
Zrzut ekranu symulacji

Początkowo, symulacja uruchamia się ze ścianą oddzielającą robota od reszty pomieszczenia. W ten sposób zasięg skanera w żadnym punkcie nie przekracza 3 metrów.

Możliwe jest usunięcie przedzielającej ściany w gazebo. Wystarczy zaznaczyć ją kliknięciem myszki i usunąć klawiszem delete. Wtedy po prawej stronie pomieszczenia skany będą większe niż 3 metry.

5. Uruchomienie drzewa behawioralnego

Mając uruchomioną symulację (jeszcze z obecną ścianą przedzielającą), możliwe jest uruchomienie node’a drzewa behawioralnego:

ros2 run turtlebot3_bt run_bt.py

W przypadku błędów z uruchomieniem może okazać się konieczne wywołanie poleceń:

apt install -y ros-humble-py-trees-ros
source install/setup.bash

W tej sytuacji robot zacznie kręcić się w kółko i zbierać dane ze skanera, a w terminalu z uruchomionym nodem będzie widoczny aktualna struktura i stan drzewa.

Na ten moment, niezależnie od obecności ściany przedzielającej pomieszczenie, robot będzie robił to samo.

Możliwe jest podejrzenie zawartości Tablicy:

py-trees-blackboard-watcher

6. Zadanie do samodzielnej realizacji

W skrypcie run_bt.py zaznaczono punkty TODO.

W skrypcie behaviours.py należy utworzyć nowe zachowanie Drive, które wysyła komendę jazdy prosto z prędkością przekazywaną przez argument vel.

Nastepnie należy tak zmodyfikować skrypt run_bt.py, aby realizował założenia z punktu 2. Cel zajęć.

Na eKursy proszę udostępnić:

7. Dodatkowe materiały


Autor: Kamil Młodzikowski